home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / TEMP / GNU / flex / Actions < prev    next >
Text File  |  1995-06-28  |  9KB  |  284 lines

  1. Actions
  2. Previous: <Matching=>Matching> * Next: <Generated scanner=>Generateds> * Up: <Top=>!Root>
  3.  
  4. #Wrap on
  5. {fH3}Actions{f}
  6.  
  7. Each pattern in a rule has a corresponding action, which
  8. can be any arbitrary C statement.  The pattern ends at the
  9. first non-escaped whitespace character; the remainder of
  10. the line is its action.  If the action is empty, then when
  11. the pattern is matched the input token is simply
  12. discarded.  For example, here is the specification for a
  13. program which deletes all occurrences of "zap me" from its
  14. input:
  15.  
  16. #Wrap off
  17. #fCode
  18. %%
  19. "zap me"
  20. #f
  21. #Wrap on
  22.  
  23. (It will copy all other characters in the input to the
  24. output since they will be matched by the default rule.)
  25.  
  26. Here is a program which compresses multiple blanks and
  27. tabs down to a single blank, and throws away whitespace
  28. found at the end of a line:
  29.  
  30. #Wrap off
  31. #fCode
  32. %%
  33. [ \\t]+        putchar( ' ' );
  34. [ \\t]+$       \/\* ignore this token \*\/
  35. #f
  36. #Wrap on
  37.  
  38. If the action contains a '\{', then the action spans till
  39. the balancing '\}' is found, and the action may cross
  40. multiple lines.  {fCode}flex{f} knows about C strings and comments and
  41. won't be fooled by braces found within them, but also
  42. allows actions to begin with {fEmphasis}%\{{f} and will consider the
  43. action to be all the text up to the next {fEmphasis}%\}{f} (regardless of
  44. ordinary braces inside the action).
  45.  
  46. An action consisting solely of a vertical bar ('|') means
  47. "same as the action for the next rule." See below for an
  48. illustration.
  49.  
  50. Actions can include arbitrary C code, including {fCode}return{f}
  51. statements to return a value to whatever routine called
  52. {fEmphasis}yylex(){f}.  Each time {fEmphasis}yylex(){f} is called it continues
  53. processing tokens from where it last left off until it either
  54. reaches the end of the file or executes a return.
  55.  
  56. Actions are free to modify {fCode}yytext{f} except for lengthening
  57. it (adding characters to its end--these will overwrite
  58. later characters in the input stream).  This however does
  59. not apply when using {fEmphasis}%array{f} (see above); in that case,
  60. {fCode}yytext{f} may be freely modified in any way.
  61.  
  62. Actions are free to modify {fCode}yyleng{f} except they should not
  63. do so if the action also includes use of {fEmphasis}yymore(){f} (see
  64. below).
  65.  
  66. There are a number of special directives which can be
  67. included within an action:
  68.  
  69. #Indent +4
  70.  
  71.  - {fEmphasis}ECHO{f} copies yytext to the scanner's output.
  72.  
  73.  
  74.  - {fCode}BEGIN{f} followed by the name of a start condition
  75. places the scanner in the corresponding start
  76. condition (see below).
  77.  
  78.  
  79.  - {fCode}REJECT{f} directs the scanner to proceed on to the
  80. "second best" rule which matched the input (or a
  81. prefix of the input).  The rule is chosen as
  82. described above in "How the Input is Matched", and
  83. {fCode}yytext{f} and {fCode}yyleng{f} set up appropriately.  It may
  84. either be one which matched as much text as the
  85. originally chosen rule but came later in the {fCode}flex{f}
  86. input file, or one which matched less text.  For
  87. example, the following will both count the words in
  88. the input and call the routine special() whenever
  89. "frob" is seen:
  90.  
  91. #Wrap off
  92. #fCode
  93.         int word\_count = 0;
  94. %%
  95.  
  96. frob        special(); REJECT;
  97. [^ \\t\\n]+   ++word\_count;
  98. #f
  99. #Wrap on
  100.  
  101. Without the {fCode}REJECT{f}, any "frob"'s in the input would
  102. not be counted as words, since the scanner normally
  103. executes only one action per token.  Multiple
  104. {fCode}REJECT's{f} are allowed, each one finding the next
  105. best choice to the currently active rule.  For
  106. example, when the following scanner scans the token
  107. "abcd", it will write "abcdabcaba" to the output:
  108.  
  109. #Wrap off
  110. #fCode
  111. %%
  112. a        |
  113. ab       |
  114. abc      |
  115. abcd     ECHO; REJECT;
  116. .|\\n     \/\* eat up any unmatched character \*\/
  117. #f
  118. #Wrap on
  119.  
  120. (The first three rules share the fourth's action
  121. since they use the special '|' action.)  {fCode}REJECT{f} is
  122. a particularly expensive feature in terms of
  123. scanner performance; if it is used in {fEmphasis}any{f} of the
  124. scanner's actions it will slow down {fEmphasis}all{f} of the
  125. scanner's matching.  Furthermore, {fCode}REJECT{f} cannot be used
  126. with the {fEmphasis}-Cf{f} or {fEmphasis}-CF{f} options (see below).
  127.  
  128. Note also that unlike the other special actions,
  129. {fCode}REJECT{f} is a {fEmphasis}branch{f}; code immediately following it
  130. in the action will {fEmphasis}not{f} be executed.
  131.  
  132.  
  133.  - {fEmphasis}yymore(){f} tells the scanner that the next time it
  134. matches a rule, the corresponding token should be
  135. {fEmphasis}appended{f} onto the current value of {fCode}yytext{f} rather
  136. than replacing it.  For example, given the input
  137. "mega-kludge" the following will write
  138. "mega-mega-kludge" to the output:
  139.  
  140. #Wrap off
  141. #fCode
  142. %%
  143. mega-    ECHO; yymore();
  144. kludge   ECHO;
  145. #f
  146. #Wrap on
  147.  
  148. First "mega-" is matched and echoed to the output.
  149. Then "kludge" is matched, but the previous "mega-"
  150. is still hanging around at the beginning of {fCode}yytext{f}
  151. so the {fEmphasis}ECHO{f} for the "kludge" rule will actually
  152. write "mega-kludge".
  153.  
  154. #Indent
  155.  
  156. Two notes regarding use of {fEmphasis}yymore(){f}.  First, {fEmphasis}yymore(){f}
  157. depends on the value of {fCode}yyleng{f} correctly reflecting the
  158. size of the current token, so you must not modify {fCode}yyleng{f}
  159. if you are using {fEmphasis}yymore(){f}.  Second, the presence of
  160. {fEmphasis}yymore(){f} in the scanner's action entails a minor
  161. performance penalty in the scanner's matching speed.
  162.  
  163. #Indent +4
  164.  
  165.  - {fEmphasis}yyless(n){f} returns all but the first {fStrong}n{f} characters of
  166. the current token back to the input stream, where
  167. they will be rescanned when the scanner looks for
  168. the next match.  {fCode}yytext{f} and {fCode}yyleng{f} are adjusted
  169. appropriately (e.g., {fCode}yyleng{f} will now be equal to {fStrong}n{f}
  170. ).  For example, on the input "foobar" the
  171. following will write out "foobarbar":
  172.  
  173. #Wrap off
  174. #fCode
  175. %%
  176. foobar    ECHO; yyless(3);
  177. [a-z]+    ECHO;
  178. #f
  179. #Wrap on
  180.  
  181. An argument of 0 to {fCode}yyless{f} will cause the entire
  182. current input string to be scanned again.  Unless
  183. you've changed how the scanner will subsequently
  184. process its input (using {fCode}BEGIN{f}, for example), this
  185. will result in an endless loop.
  186.  
  187. Note that {fCode}yyless{f} is a macro and can only be used in the
  188. flex input file, not from other source files.
  189.  
  190.  
  191.  - {fEmphasis}unput(c){f} puts the character {fCode}c{f} back onto the input
  192. stream.  It will be the next character scanned.
  193. The following action will take the current token
  194. and cause it to be rescanned enclosed in
  195. parentheses.
  196.  
  197. #Wrap off
  198. #fCode
  199. \{
  200. int i;
  201. \/\* Copy yytext because unput() trashes yytext \*\/
  202. char \*yycopy = strdup( yytext );
  203. unput( ')' );
  204. for ( i = yyleng - 1; i >= 0; --i )
  205.     unput( yycopy[i] );
  206. unput( '(' );
  207. free( yycopy );
  208. \}
  209. #f
  210. #Wrap on
  211.  
  212. Note that since each {fEmphasis}unput(){f} puts the given
  213. character back at the {fEmphasis}beginning{f} of the input stream,
  214. pushing back strings must be done back-to-front.
  215. An important potential problem when using {fEmphasis}unput(){f} is that
  216. if you are using {fEmphasis}%pointer{f} (the default), a call to {fEmphasis}unput(){f}
  217. {fEmphasis}destroys{f} the contents of {fCode}yytext{f}, starting with its
  218. rightmost character and devouring one character to the left
  219. with each call.  If you need the value of yytext preserved
  220. after a call to {fEmphasis}unput(){f} (as in the above example), you
  221. must either first copy it elsewhere, or build your scanner
  222. using {fEmphasis}%array{f} instead (see How The Input Is Matched).
  223.  
  224. Finally, note that you cannot put back {fCode}EOF{f} to attempt to
  225. mark the input stream with an end-of-file.
  226.  
  227.  
  228.  - {fEmphasis}input(){f} reads the next character from the input
  229. stream.  For example, the following is one way to
  230. eat up C comments:
  231.  
  232. #Wrap off
  233. #fCode
  234. %%
  235. "\/\*"        \{
  236.             register int c;
  237.  
  238.             for ( ; ; )
  239.                 \{
  240.                 while ( (c = input()) != '\*' &&
  241.                         c != EOF )
  242.                     ;    \/\* eat up text of comment \*\/
  243.  
  244.                 if ( c == '\*' )
  245.                     \{
  246.                     while ( (c = input()) == '\*' )
  247.                         ;
  248.                     if ( c == '\/' )
  249.                         break;    \/\* found the end \*\/
  250.                     \}
  251.  
  252.                 if ( c == EOF )
  253.                     \{
  254.                     error( "EOF in comment" );
  255.                     break;
  256.                     \}
  257.                 \}
  258.             \}
  259. #f
  260. #Wrap on
  261.  
  262. (Note that if the scanner is compiled using {fEmphasis}C++{f},
  263. then {fEmphasis}input(){f} is instead referred to as {fEmphasis}yyinput(){f},
  264. in order to avoid a name clash with the {fEmphasis}C++{f} stream
  265. by the name of {fCode}input{f}.)
  266.  
  267.  
  268.  - flushes the scanner's internal buffer so that the next time the scanner
  269. attempts to match a token, it will first refill the buffer using
  270. {fCode}YY\_INPUT{f} (see The Generated Scanner, below).  This action is
  271. a special case of the more general {fEmphasis}yy\_flush\_buffer(){f} function,
  272. described below in the section Multiple Input Buffers.
  273.  
  274.  
  275.  - {fEmphasis}yyterminate(){f} can be used in lieu of a return
  276. statement in an action.  It terminates the scanner
  277. and returns a 0 to the scanner's caller, indicating
  278. "all done".  By default, {fEmphasis}yyterminate(){f} is also
  279. called when an end-of-file is encountered.  It is a
  280. macro and may be redefined.
  281.  
  282. #Indent
  283.  
  284.